package site.isscloud.web.controller.project;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import site.isscloud.common.core.controller.BaseController;
import site.isscloud.common.core.domain.AjaxResult;
import site.isscloud.project.domain.PjLocation;
import site.isscloud.project.domain.PjAlarmEvent;
import site.isscloud.project.service.BuildingService;
import site.isscloud.project.service.IPjLocationService;
import site.isscloud.project.service.IPjAlarmEventService;

import java.util.*;
import java.util.stream.Collectors;
import java.math.BigDecimal;

/**
 * 空间位置温度监测控制器
 */
@RestController
@RequestMapping("/project/location-monitor")
public class LocationTemperatureController extends BaseController {

    @Autowired
    private IPjLocationService locationService;

    @Autowired
    private BuildingService buildingService;

    @Autowired
    private IPjAlarmEventService alarmEventService;

    /**
     * 获取楼栋-单元-电梯监视卡片数据
     */
    @GetMapping("/monitor-cards")
    public AjaxResult getMonitorCards() {
        try {
            // 查询所有活跃的空间位置
            PjLocation queryParam = new PjLocation();
            queryParam.setStatus("0"); // 假设0表示正常状态
            List<PjLocation> allLocations = locationService.selectPjLocationList(queryParam);

            // 获取所有活跃的温度告警事件
            List<PjAlarmEvent> activeTemperatureAlarms = alarmEventService.selectActiveEvents().stream()
                    .filter(event -> event.getAlarmType() != null && event.getAlarmType() == 3) // 温度告警
                    .collect(Collectors.toList());

            // 直接获取最新的温度统计数据
            Map<String, Map<String, Object>> latestTemperatureStats = buildingService.getLatestTemperatureStats();

            // 构建监视卡片数据
            Map<String, Object> result = buildMonitorCardsData(allLocations, activeTemperatureAlarms, latestTemperatureStats);

            return AjaxResult.success(result);
        } catch (Exception e) {
            logger.error("获取监视卡片数据失败", e);
            return AjaxResult.error("获取监视卡片数据失败");
        }
    }

    /**
     * 获取电梯温度详情 - 修改为使用 lcId
     */
    @GetMapping("/elevator-detail/{lcId}")
    public AjaxResult getElevatorDetail(@PathVariable String lcId) {
        try {
            // 使用 BuildingService 获取电梯详情
            Map<String, Object> detail = buildingService.getElevatorDetail(lcId);
            return AjaxResult.success(detail);
        } catch (Exception e) {
            logger.error("获取电梯详情失败，lcId: {}", lcId, e);
            return AjaxResult.error("获取电梯详情失败: " + e.getMessage());
        }
    }

    /**
     * 获取电梯温度趋势数据 - 修改为使用 lcId
     */
    @GetMapping("/temperature-trend")
    public AjaxResult getTemperatureTrend(
            @RequestParam String lcId,
            @RequestParam String timeType,
            @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime,
            @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime) {
        try {
            // 使用 BuildingService 获取温度趋势数据
            Map<String, Object> trendData = buildingService.getTemperatureTrend(lcId, timeType, startTime, endTime);
            return AjaxResult.success(trendData);
        } catch (Exception e) {
            logger.error("获取温度趋势数据失败，lcId: {}, timeType: {}", lcId, timeType, e);
            return AjaxResult.error("获取温度趋势数据失败: " + e.getMessage());
        }
    }

    /**
     * 获取实时温度数据
     */
    @GetMapping("/realtime-temperature")
    public AjaxResult getRealtimeTemperature(@RequestParam String lcId) {
        try {
            // 获取电梯信息
            Map<String, Object> elevatorDetail = buildingService.getElevatorDetail(lcId);
            if (elevatorDetail == null || !elevatorDetail.containsKey("elevatorInfo")) {
                return AjaxResult.error("未找到对应的电梯信息");
            }

            Object elevatorInfo = elevatorDetail.get("elevatorInfo");
            if (!(elevatorInfo instanceof PjLocation)) {
                return AjaxResult.error("电梯信息格式错误");
            }

            PjLocation elevator = (PjLocation) elevatorInfo;
            Map<String, Object> realtimeData = buildingService.generateRealtimeChartData(elevator);
            return AjaxResult.success(realtimeData);
        } catch (Exception e) {
            logger.error("获取实时温度数据失败，lcId: {}", lcId, e);
            return AjaxResult.error("获取实时温度数据失败: " + e.getMessage());
        }
    }

    /**
     * 刷新监视数据
     */
    @PostMapping("/refresh")
    public AjaxResult refreshMonitorData() {
        try {
            // 这里可以添加数据刷新逻辑，比如重新统计最新数据
            // 暂时返回成功消息
            return AjaxResult.success("数据刷新成功");
        } catch (Exception e) {
            logger.error("刷新数据失败", e);
            return AjaxResult.error("刷新数据失败");
        }
    }

    // ========== 私有方法 ==========

    /**
     * 构建监视卡片数据 - 修正层级关系
     */
    private Map<String, Object> buildMonitorCardsData(List<PjLocation> locations,
                                                      List<PjAlarmEvent> activeAlarms,
                                                      Map<String, Map<String, Object>> temperatureStats) {
        Map<String, Object> result = new HashMap<>();

        // 按层级分类 - 修正层级关系
        List<Map<String, Object>> buildings = locations.stream()
                .filter(location -> location.getLevel() == 3) // 楼栋层级
                .map(location -> buildLocationCardData(location, activeAlarms, temperatureStats))
                .collect(Collectors.toList());

        List<Map<String, Object>> units = locations.stream()
                .filter(location -> location.getLevel() == 4) // 单元层级
                .map(location -> buildLocationCardData(location, activeAlarms, temperatureStats))
                .collect(Collectors.toList());

        List<Map<String, Object>> elevators = locations.stream()
                .filter(location -> location.getLevel() == 5) // 电梯层级
                .map(location -> buildLocationCardData(location, activeAlarms, temperatureStats))
                .collect(Collectors.toList());

        // 建立父子关系
        establishParentChildRelationships(buildings, units, elevators);

        result.put("buildings", buildings);
        result.put("units", units);
        result.put("elevators", elevators);

        return result;
    }

    /**
     * 建立父子关系
     */
    private void establishParentChildRelationships(List<Map<String, Object>> buildings,
                                                   List<Map<String, Object>> units,
                                                   List<Map<String, Object>> elevators) {

        // 为单元设置父级楼栋关系
        for (Map<String, Object> unit : units) {
            String unitCode = (String) unit.get("lcCode");
            String parentBuildingCode = extractParentCode(unitCode, 3);
            unit.put("parentCode", parentBuildingCode);
        }

        // 为电梯设置父级单元关系
        for (Map<String, Object> elevator : elevators) {
            String elevatorCode = (String) elevator.get("lcCode");
            String parentUnitCode = extractParentCode(elevatorCode, 4);
            elevator.put("parentCode", parentUnitCode);
        }

        // 为楼栋设置子单元数量
        for (Map<String, Object> building : buildings) {
            String buildingCode = (String) building.get("lcCode");
            long unitCount = units.stream()
                    .filter(unit -> buildingCode.equals(unit.get("parentCode")))
                    .count();
            building.put("unitCount", unitCount);
        }

        // 为单元设置子电梯数量
        for (Map<String, Object> unit : units) {
            String unitCode = (String) unit.get("lcCode");
            long elevatorCount = elevators.stream()
                    .filter(elevator -> unitCode.equals(elevator.get("parentCode")))
                    .count();
            unit.put("elevatorCount", elevatorCount);
        }
    }

    /**
     * 提取父级编码
     */
    private String extractParentCode(String lcCode, int targetLevel) {
        if (lcCode == null) return null;

        String[] parts = lcCode.split("-");
        if (parts.length <= targetLevel) return null;

        // 构建父级编码
        StringBuilder parentCode = new StringBuilder();
        for (int i = 0; i < targetLevel; i++) {
            if (i > 0) parentCode.append("-");
            parentCode.append(parts[i]);
        }

        return parentCode.toString();
    }

    /**
     * 构建位置卡片数据
     */
    private Map<String, Object> buildLocationCardData(PjLocation location,
                                                      List<PjAlarmEvent> activeAlarms,
                                                      Map<String, Map<String, Object>> temperatureStats) {
        Map<String, Object> card = new HashMap<>();
        card.put("lcId", location.getLcId());
        card.put("lcCode", location.getLcCode());
        card.put("lcName", location.getLcName());
        card.put("lcDesc", location.getLcDesc());
        card.put("level", location.getLevel());
        card.put("levelName", location.getLevelName());

        // 设备信息
        card.put("deviceNo", location.getDeviceNo());
        card.put("channelNo", location.getChannelNo());
        card.put("startMeter", location.getStartMeter());
        card.put("endMeter", location.getEndMeter());

        // 监控状态 - 使用真实数据
         Map<String, Object> monitorStatus = generateRealMonitorStatus(location, activeAlarms, temperatureStats);
         card.put("monitorStatus", monitorStatus);

        return card;
    }

    /**
     * 生成真实的监控状态
     */
    private Map<String, Object> generateRealMonitorStatus(PjLocation location,
                                                          List<PjAlarmEvent> activeAlarms,
                                                          Map<String, Map<String, Object>> temperatureStats) {
        Map<String, Object> status = new HashMap<>();

        // 获取该位置相关的告警事件
        List<PjAlarmEvent> locationAlarms = getAlarmsForLocation(location, activeAlarms);

        // 获取该位置的温度统计数据
        Map<String, Object> locationTempStats = temperatureStats.get(location.getLcCode());

        if (locationTempStats != null) {
            // 使用最新的温度统计数据
            setTemperatureStatsFromDatabase(status, locationTempStats);
        } else {
            // 如果没有统计数据，使用默认值
            setDefaultTemperatureStats(status);
        }

        // 设置告警状态
        if (locationAlarms.isEmpty()) {
            // 没有告警，状态正常
            status.put("status", 0);
            status.put("statusText", "正常");
            status.put("alarmCount", 0);
        } else {
            // 有告警，状态为报警
            status.put("status", 2);
            status.put("statusText", "报警");
            status.put("alarmCount", locationAlarms.size());

            // 如果是电梯层级，设置异常楼层信息
            if (location.getLevel() == 5) {
                status.put("abnormalFloors", buildingService.getAbnormalFloors(location, locationAlarms));
            }
        }

        // 新增：获取预警楼层数据（仅对电梯层级）
        if (location.getLevel() == 5) {
            List<String> warningFloors = buildingService.getWarningFloors(location);
            status.put("warningFloors", warningFloors);
        } else {
            status.put("warningFloors", new ArrayList<>());
        }

        return status;
    }

    /**
     * 从数据库温度统计数据设置温度信息
     */
    private void setTemperatureStatsFromDatabase(Map<String, Object> status, Map<String, Object> tempStats) {
        try {
            // 从数据库记录中提取温度数据
            Double maxTemp = getDoubleValue(tempStats, "max_temperature");
            Double minTemp = getDoubleValue(tempStats, "min_temperature");
            Double avgTemp = getDoubleValue(tempStats, "avg_temperature");

            if (maxTemp != null) {
                status.put("maxTemp", Math.round(maxTemp * 10) / 10.0);
                status.put("currentTemp", Math.round(maxTemp * 10) / 10.0); // 当前温度使用最高温度
            } else {
                status.put("maxTemp", 30.0);
                status.put("currentTemp", 30.0);
            }

            if (minTemp != null) {
                status.put("minTemp", Math.round(minTemp * 10) / 10.0);
            } else {
                status.put("minTemp", 25.0);
            }

            logger.debug("设置温度数据 - 最高温度: {}, 最低温度: {}, 平均温度: {}", maxTemp, minTemp, avgTemp);

        } catch (Exception e) {
            logger.error("设置数据库温度数据失败", e);
            setDefaultTemperatureStats(status);
        }
    }

    /**
     * 获取Map中的Double值
     */
    private Double getDoubleValue(Map<String, Object> map, String key) {
        try {
            Object value = map.get(key);
            if (value instanceof BigDecimal) {
                return ((BigDecimal) value).doubleValue();
            } else if (value instanceof Double) {
                return (Double) value;
            } else if (value instanceof Integer) {
                return ((Integer) value).doubleValue();
            } else if (value instanceof String) {
                return Double.parseDouble((String) value);
            }
            return null;
        } catch (Exception e) {
            logger.warn("转换温度数据失败 - key: {}, value: {}", key, map.get(key));
            return null;
        }
    }

    /**
     * 获取位置相关的告警事件
     */
    private List<PjAlarmEvent> getAlarmsForLocation(PjLocation location, List<PjAlarmEvent> activeAlarms) {
        return activeAlarms.stream()
                .filter(alarm -> isAlarmInLocationRange(alarm, location))
                .collect(Collectors.toList());
    }

    /**
     * 判断告警是否在位置范围内
     */
    private boolean isAlarmInLocationRange(PjAlarmEvent alarm, PjLocation location) {
        if (alarm.getMeterMark() == null) {
            return false;
        }

        Integer meterMark = alarm.getMeterMark();
        Integer startMeter = location.getStartMeter();
        Integer endMeter = location.getEndMeter();

        // 检查告警米标是否在位置的米标范围内
        return startMeter != null && endMeter != null &&
                meterMark >= startMeter && meterMark <= endMeter;
    }

    /**
     * 设置默认温度统计
     */
    private void setDefaultTemperatureStats(Map<String, Object> status) {
        double baseTemp = 25.0;
        status.put("currentTemp", baseTemp);
        status.put("maxTemp", baseTemp + 5.0);
        status.put("minTemp", baseTemp - 5.0);
    }
}